---
title: 动态类型系统对比
description: 深入理解 Python 和 JavaScript 动态类型系统的差异，掌握类型转换规则、真值判断和类型检查方法。
---

# 动态类型系统对比

Python 和 JavaScript 都是动态类型语言，但它们在类型处理上有显著差异。Python 是强类型动态语言，而 JavaScript 是弱类型动态语言。本模块将帮助你理解这些差异，避免常见的类型相关陷阱。

## 类型系统基础概念

### 强类型 vs 弱类型

<PythonEditor title="类型系统差异" compare={true}>
```python !! py
# Python：强类型动态语言
# 不允许隐式类型转换，类型检查严格

# 基本类型
number = 42
text = "Hello"
flag = True
empty = None

print(f"数字类型: {type(number)}")
print(f"字符串类型: {type(text)}")
print(f"布尔类型: {type(flag)}")
print(f"空值类型: {type(empty)}")

# 严格的类型检查
try:
    result = "5" + 3  # 错误：不能将字符串和数字相加
except TypeError as e:
    print(f"类型错误: {e}")

try:
    result = "5" * 3  # 可以：字符串重复
    print(f"字符串重复: {result}")
except TypeError as e:
    print(f"错误: {e}")

# 显式类型转换
num_str = "123"
num_int = int(num_str)      # 显式转换为整数
num_float = float(num_str)  # 显式转换为浮点数
bool_val = bool(num_str)    # 显式转换为布尔值

print(f"转换结果: {num_int}, {num_float}, {bool_val}")

# 类型检查函数
def process_data(data):
    if isinstance(data, str):
        return f"处理字符串: {data.upper()}"
    elif isinstance(data, int):
        return f"处理整数: {data * 2}"
    elif isinstance(data, list):
        return f"处理列表: {len(data)} 个元素"
    else:
        return f"未知类型: {type(data)}"

print(process_data("hello"))
print(process_data(42))
print(process_data([1, 2, 3]))
```

```javascript !! js
// JavaScript：弱类型动态语言
// 允许隐式类型转换，类型检查宽松

// 基本类型
let number = 42;
let text = "Hello";
let flag = true;
let empty = null;
let notDefined = undefined;

console.log(`数字类型: ${typeof number}`);
console.log(`字符串类型: ${typeof text}`);
console.log(`布尔类型: ${typeof flag}`);
console.log(`空值类型: ${typeof empty}`);      // "object" (历史遗留问题)
console.log(`未定义类型: ${typeof notDefined}`);

// 宽松的类型检查 - 隐式类型转换
let result1 = "5" + 3;    // "53" - 字符串拼接
let result2 = "5" - 3;    // 2 - 数字运算
let result3 = "5" * 3;    // 15 - 数字运算
let result4 = "5" / 3;    // 1.666... - 数字运算

console.log(`"5" + 3 = ${result1}`);
console.log(`"5" - 3 = ${result2}`);
console.log(`"5" * 3 = ${result3}`);
console.log(`"5" / 3 = ${result4}`);

// 更多隐式转换示例
console.log(`true + 1 = ${true + 1}`);        // 2
console.log(`false + 1 = ${false + 1}`);      // 1
console.log(`null + 1 = ${null + 1}`);        // 1
console.log(`undefined + 1 = ${undefined + 1}`); // NaN

// 显式类型转换
let numStr = "123";
let numInt = parseInt(numStr);        // 转换为整数
let numFloat = parseFloat(numStr);    // 转换为浮点数
let numNumber = Number(numStr);       // 通用数字转换
let boolVal = Boolean(numStr);        // 转换为布尔值

console.log(`转换结果: ${numInt}, ${numFloat}, ${numNumber}, ${boolVal}`);

// 类型检查函数
function processData(data) {
    if (typeof data === 'string') {
        return `处理字符串: ${data.toUpperCase()}`;
    } else if (typeof data === 'number') {
        return `处理数字: ${data * 2}`;
    } else if (Array.isArray(data)) {
        return `处理数组: ${data.length} 个元素`;
    } else {
        return `未知类型: ${typeof data}`;
    }
}

console.log(processData("hello"));
console.log(processData(42));
console.log(processData([1, 2, 3]));
```
</PythonEditor>

## 真值和假值判断

### 真值表对比

<PythonEditor title="真值判断对比" compare={true}>
```python !! py
# Python 真值判断

# Python 中的假值（Falsy）
falsy_values = [
    False,      # 布尔值 False
    None,       # None 值
    0,          # 数字 0
    0.0,        # 浮点数 0.0
    0j,         # 复数 0
    "",         # 空字符串
    [],         # 空列表
    (),         # 空元组
    {},         # 空字典
    set(),      # 空集合
]

print("Python 假值测试:")
for value in falsy_values:
    print(f"{repr(value):15} -> {bool(value)}")

# 真值测试
print("\nPython 真值测试:")
truthy_values = [
    True,           # 布尔值 True
    1,              # 非零数字
    -1,             # 负数
    "0",            # 非空字符串（即使是 "0"）
    "False",        # 非空字符串（即使是 "False"）
    [0],            # 非空列表
    (None,),        # 非空元组
    {"key": None},  # 非空字典
]

for value in truthy_values:
    print(f"{repr(value):15} -> {bool(value)}")

# 条件判断中的应用
def check_data(data):
    if data:  # 使用真值判断
        print(f"数据存在: {data}")
    else:
        print("数据为空或不存在")

# 测试
check_data([])          # 空列表 -> False
check_data([0])         # 非空列表 -> True
check_data("")          # 空字符串 -> False
check_data("0")         # 非空字符串 -> True

# 逻辑运算符的短路特性
print("\nPython 短路运算:")
result1 = [] or "默认值"              # "默认值"
result2 = [1, 2, 3] or "默认值"       # [1, 2, 3]
result3 = None and "不会执行"         # None
result4 = "存在" and "会执行"         # "会执行"

print(f"[] or '默认值' = {result1}")
print(f"[1, 2, 3] or '默认值' = {result2}")
print(f"None and '不会执行' = {result3}")
print(f"'存在' and '会执行' = {result4}")
```

```javascript !! js
// JavaScript 真值判断

// JavaScript 中的假值（Falsy）
const falsyValues = [
    false,      // 布尔值 false
    null,       // null 值
    undefined,  // undefined 值
    0,          // 数字 0
    -0,         // 负零
    0n,         // BigInt 0
    NaN,        // Not a Number
    "",         // 空字符串
    // 注意：JavaScript 中空数组 [] 和空对象 {} 是真值！
];

console.log("JavaScript 假值测试:");
falsyValues.forEach(value => {
    console.log(`${String(value).padEnd(15)} -> ${Boolean(value)}`);
});

// 真值测试
console.log("\nJavaScript 真值测试:");
const truthyValues = [
    true,           // 布尔值 true
    1,              // 非零数字
    -1,             // 负数
    "0",            // 非空字符串（即使是 "0"）
    "false",        // 非空字符串（即使是 "false"）
    [],             // 空数组（注意：在 JS 中是真值！）
    {},             // 空对象（注意：在 JS 中是真值！）
    function() {},  // 函数
    Infinity,       // 无穷大
    -Infinity,      // 负无穷大
];

truthyValues.forEach(value => {
    console.log(`${String(value).padEnd(15)} -> ${Boolean(value)}`);
});

// 特别注意：JavaScript 中的 [] 和 {} 是真值
console.log("\n特别注意 - JavaScript 特殊情况:");
console.log(`[] == false: ${[] == false}`);        // true（类型转换）
console.log(`Boolean([]): ${Boolean([])}`);        // true（真值）
console.log(`{} == false: ${{} == false}`);        // false
console.log(`Boolean({}): ${Boolean({})}`);        // true（真值）

// 条件判断中的应用
function checkData(data) {
    if (data) {  // 使用真值判断
        console.log(`数据存在: ${data}`);
    } else {
        console.log("数据为空或不存在");
    }
}

// 测试
checkData([]);          // 空数组 -> true（JavaScript 特殊性）
checkData([0]);         // 非空数组 -> true
checkData("");          // 空字符串 -> false
checkData("0");         // 非空字符串 -> true
checkData(null);        // null -> false
checkData(undefined);   // undefined -> false

// 逻辑运算符的短路特性
console.log("\nJavaScript 短路运算:");
let result1 = [] || "默认值";              // [] (因为 [] 是真值)
let result2 = null || "默认值";            // "默认值"
let result3 = undefined && "不会执行";     // undefined
let result4 = "存在" && "会执行";          // "会执行"

console.log(`[] || '默认值' = ${result1}`);
console.log(`null || '默认值' = ${result2}`);
console.log(`undefined && '不会执行' = ${result3}`);
console.log(`'存在' && '会执行' = ${result4}`);

// 空值合并运算符（ES2020+）
let value1 = null ?? "默认值";           // "默认值"
let value2 = 0 ?? "默认值";              // 0 (因为 0 不是 null 或 undefined)
let value3 = "" ?? "默认值";             // "" (因为 "" 不是 null 或 undefined)

console.log(`null ?? '默认值' = ${value1}`);
console.log(`0 ?? '默认值' = ${value2}`);
console.log(`"" ?? '默认值' = ${value3}`);
```
</PythonEditor>

## 类型转换详解

### 数字类型转换

<PythonEditor title="数字类型转换" compare={true}>
```python !! py
# Python 数字类型转换

# 字符串到数字
try:
    int_val = int("123")        # 123
    float_val = float("123.45") # 123.45
    print(f"字符串转数字: {int_val}, {float_val}")
    
    # 不同进制
    binary = int("1010", 2)     # 二进制 -> 10
    octal = int("123", 8)       # 八进制 -> 83
    hex_val = int("ff", 16)     # 十六进制 -> 255
    print(f"进制转换: {binary}, {octal}, {hex_val}")
    
except ValueError as e:
    print(f"转换错误: {e}")

# 数字到字符串
num = 123.456
str_val = str(num)          # "123.456"
formatted = f"{num:.2f}"    # "123.46"
print(f"数字转字符串: {str_val}, {formatted}")

# 布尔值转换
print(f"bool(0): {bool(0)}")            # False
print(f"bool(1): {bool(1)}")            # True
print(f"bool(-1): {bool(-1)}")          # True
print(f"int(True): {int(True)}")        # 1
print(f"int(False): {int(False)}")      # 0

# 特殊值处理
try:
    invalid = int("abc")
except ValueError:
    print("无法转换 'abc' 为整数")

# 安全转换函数
def safe_int(value, default=0):
    try:
        return int(value)
    except (ValueError, TypeError):
        return default

print(f"安全转换: {safe_int('123')}")    # 123
print(f"安全转换: {safe_int('abc')}")    # 0
print(f"安全转换: {safe_int(None)}")     # 0

# 类型检查
value = 42
if isinstance(value, int):
    print("这是一个整数")
elif isinstance(value, float):
    print("这是一个浮点数")
```

```javascript !! js
// JavaScript 数字类型转换

// 字符串到数字
let intVal = parseInt("123");           // 123
let floatVal = parseFloat("123.45");    // 123.45
let numberVal = Number("123.45");       // 123.45
let unaryVal = +"123.45";               // 123.45 (一元加号)

console.log(`字符串转数字: ${intVal}, ${floatVal}, ${numberVal}, ${unaryVal}`);

// 不同进制（parseInt 支持）
let binary = parseInt("1010", 2);       // 二进制 -> 10
let octal = parseInt("123", 8);         // 八进制 -> 83
let hexVal = parseInt("ff", 16);        // 十六进制 -> 255

console.log(`进制转换: ${binary}, ${octal}, ${hexVal}`);

// 数字到字符串
let num = 123.456;
let strVal = String(num);               // "123.456"
let toStringVal = num.toString();       // "123.456"
let fixedVal = num.toFixed(2);          // "123.46"

console.log(`数字转字符串: ${strVal}, ${toStringVal}, ${fixedVal}`);

// 布尔值转换
console.log(`Boolean(0): ${Boolean(0)}`);           // false
console.log(`Boolean(1): ${Boolean(1)}`);           // true
console.log(`Boolean(-1): ${Boolean(-1)}`);         // true
console.log(`Number(true): ${Number(true)}`);       // 1
console.log(`Number(false): ${Number(false)}`);     // 0

// 特殊值处理
let invalid = parseInt("abc");          // NaN
console.log(`parseInt("abc"): ${invalid}`);
console.log(`isNaN(invalid): ${isNaN(invalid)}`);

// 更严格的 NaN 检查（ES6+）
console.log(`Number.isNaN(invalid): ${Number.isNaN(invalid)}`);

// 安全转换函数
function safeInt(value, defaultValue = 0) {
    const result = parseInt(value);
    return isNaN(result) ? defaultValue : result;
}

console.log(`安全转换: ${safeInt('123')}`);    // 123
console.log(`安全转换: ${safeInt('abc')}`);    // 0
console.log(`安全转换: ${safeInt(null)}`);     // 0

// 类型检查
let value = 42;
if (typeof value === 'number' && !isNaN(value)) {
    console.log("这是一个有效数字");
}

// 整数检查（ES6+）
if (Number.isInteger(value)) {
    console.log("这是一个整数");
}

// 特殊数字值
console.log(`Infinity + 1 = ${Infinity + 1}`);      // Infinity
console.log(`-Infinity + 1 = ${-Infinity + 1}`);    // -Infinity
console.log(`NaN + 1 = ${NaN + 1}`);                // NaN
console.log(`0 / 0 = ${0 / 0}`);                    // NaN
console.log(`1 / 0 = ${1 / 0}`);                    // Infinity

// 隐式转换陷阱
console.log("\n隐式转换陷阱:");
console.log(`"3" + 2 = ${"3" + 2}`);               // "32" (字符串拼接)
console.log(`"3" - 2 = ${"3" - 2}`);               // 1 (数字运算)
console.log(`"3" * 2 = ${"3" * 2}`);               // 6 (数字运算)
console.log(`"3" / 2 = ${"3" / 2}`);               // 1.5 (数字运算)
console.log(`[] + [] = ${[] + []}`);               // "" (空字符串)
console.log(`[] + {} = ${[] + {}}`);               // "[object Object]"
console.log(`{} + [] = ${{} + []}`);               // 0 (可能因环境而异)
```
</PythonEditor>

## 等值比较和类型检查

### 相等性比较

<PythonEditor title="相等性比较" compare={true}>
```python !! py
# Python 相等性比较

# == 运算符：值相等
print("Python == 运算符（值相等）:")
print(f"5 == 5: {5 == 5}")                    # True
print(f"5 == 5.0: {5 == 5.0}")                # True (不同类型但值相等)
print(f"'5' == 5: {'5' == 5}")                # False (不同类型)
print(f"True == 1: {True == 1}")              # True
print(f"False == 0: {False == 0}")            # True
print(f"None == None: {None == None}")         # True

# is 运算符：身份相等（同一对象）
print("\nPython is 运算符（身份相等）:")
a = [1, 2, 3]
b = [1, 2, 3]
c = a

print(f"a == b: {a == b}")          # True (值相等)
print(f"a is b: {a is b}")          # False (不是同一对象)
print(f"a is c: {a is c}")          # True (是同一对象)

# 小整数缓存
x = 256
y = 256
print(f"x is y (256): {x is y}")    # True (小整数被缓存)

x = 257
y = 257
print(f"x is y (257): {x is y}")    # False (大整数不被缓存)

# 字符串驻留
s1 = "hello"
s2 = "hello"
print(f"s1 is s2: {s1 is s2}")     # True (字符串驻留)

# None 检查
value = None
print(f"value is None: {value is None}")        # 推荐方式
print(f"value == None: {value == None}")        # 也可以，但不推荐

# 列表和字典比较
list1 = [1, 2, 3]
list2 = [1, 2, 3]
dict1 = {"a": 1, "b": 2}
dict2 = {"a": 1, "b": 2}

print(f"list1 == list2: {list1 == list2}")     # True
print(f"dict1 == dict2: {dict1 == dict2}")     # True

# 类型检查
def check_type(value):
    print(f"值: {value}")
    print(f"类型: {type(value)}")
    print(f"isinstance(int): {isinstance(value, int)}")
    print(f"isinstance(str): {isinstance(value, str)}")
    print(f"isinstance((int, float)): {isinstance(value, (int, float))}")
    print()

check_type(42)
check_type("hello")
check_type(3.14)
```

```javascript !! js
// JavaScript 相等性比较

// == 运算符：宽松相等（会进行类型转换）
console.log("JavaScript == 运算符（宽松相等）:");
console.log(`5 == 5: ${5 == 5}`);                    // true
console.log(`5 == 5.0: ${5 == 5.0}`);                // true
console.log(`'5' == 5: ${'5' == 5}`);                // true (类型转换)
console.log(`true == 1: ${true == 1}`);              // true
console.log(`false == 0: ${false == 0}`);            // true
console.log(`null == undefined: ${null == undefined}`); // true
console.log(`'' == 0: ${'' == 0}`);                  // true
console.log(`[] == 0: ${[] == 0}`);                  // true

// === 运算符：严格相等（不进行类型转换）
console.log("\nJavaScript === 运算符（严格相等）:");
console.log(`5 === 5: ${5 === 5}`);                  // true
console.log(`5 === 5.0: ${5 === 5.0}`);              // true
console.log(`'5' === 5: ${'5' === 5}`);              // false (类型不同)
console.log(`true === 1: ${true === 1}`);            // false
console.log(`false === 0: ${false === 0}`);          // false
console.log(`null === undefined: ${null === undefined}`); // false
console.log(`null === null: ${null === null}`);      // true
console.log(`undefined === undefined: ${undefined === undefined}`); // true

// 对象比较
let a = [1, 2, 3];
let b = [1, 2, 3];
let c = a;

console.log(`a == b: ${a == b}`);           // false (不同对象)
console.log(`a === b: ${a === b}`);         // false (不同对象)
console.log(`a === c: ${a === c}`);         // true (同一对象)

// 特殊的 NaN 比较
console.log(`NaN == NaN: ${NaN == NaN}`);   // false
console.log(`NaN === NaN: ${NaN === NaN}`); // false
console.log(`Object.is(NaN, NaN): ${Object.is(NaN, NaN)}`); // true (ES6+)

// Object.is() 更严格的比较（ES6+）
console.log("\nObject.is() 比较:");
console.log(`Object.is(0, -0): ${Object.is(0, -0)}`);       // false
console.log(`0 === -0: ${0 === -0}`);                       // true
console.log(`Object.is(NaN, NaN): ${Object.is(NaN, NaN)}`); // true

// 类型检查
function checkType(value) {
    console.log(`值: ${value}`);
    console.log(`typeof: ${typeof value}`);
    console.log(`Array.isArray(): ${Array.isArray(value)}`);
    console.log(`Number.isInteger(): ${Number.isInteger(value)}`);
    console.log(`Number.isNaN(): ${Number.isNaN(value)}`);
    console.log(`value instanceof Object: ${value instanceof Object}`);
    console.log();
}

checkType(42);
checkType("hello");
checkType([1, 2, 3]);
checkType({name: "test"});
checkType(NaN);

// 更精确的类型检查
function getType(value) {
    return Object.prototype.toString.call(value).slice(8, -1);
}

console.log("精确类型检查:");
console.log(`getType(42): ${getType(42)}`);           // "Number"
console.log(`getType("hello"): ${getType("hello")}`); // "String"
console.log(`getType([]): ${getType([])}`);           // "Array"
console.log(`getType({}): ${getType({})}`);           // "Object"
console.log(`getType(null): ${getType(null)}`);       // "Null"
console.log(`getType(undefined): ${getType(undefined)}`); // "Undefined"

// 类型转换陷阱示例
console.log("\n类型转换陷阱:");
console.log(`[] == ![]: ${[] == ![]}`);               // true (复杂的类型转换)
console.log(`[] == false: ${[] == false}`);          // true
console.log(`![] == false: ${![] == false}`);        // true
console.log(`Boolean([]): ${Boolean([])}`);          // true
console.log(`![]: ${![]}`);                          // false
```
</PythonEditor>

## 类型系统最佳实践

### 避免类型陷阱

<PythonEditor title="类型系统最佳实践" compare={true}>
```python !! py
# Python 类型系统最佳实践

from typing import Union, Optional, List, Dict, Any
import json

# 1. 使用类型注解（Python 3.5+）
def calculate_total(items: List[Dict[str, Union[str, float]]]) -> float:
    """计算商品总价"""
    total = 0.0
    for item in items:
        if isinstance(item.get('price'), (int, float)):
            total += float(item['price'])
    return total

# 2. 安全的类型转换
def safe_convert_to_number(value: Any) -> Optional[float]:
    """安全地将值转换为数字"""
    if value is None:
        return None
    
    try:
        if isinstance(value, (int, float)):
            return float(value)
        elif isinstance(value, str):
            # 去除空白并检查
            cleaned = value.strip()
            if cleaned:
                return float(cleaned)
            return None
    except ValueError:
        pass
    
    return None

# 3. 输入验证
def validate_user_input(data: Dict[str, Any]) -> Dict[str, str]:
    """验证用户输入"""
    errors = {}
    
    # 检查必需字段
    required_fields = ['name', 'email', 'age']
    for field in required_fields:
        if field not in data or not data[field]:
            errors[field] = f"{field} 是必需的"
    
    # 类型验证
    if 'age' in data:
        age = safe_convert_to_number(data['age'])
        if age is None or age < 0 or age > 150:
            errors['age'] = "年龄必须是 0-150 之间的数字"
    
    if 'email' in data:
        email = data['email']
        if not isinstance(email, str) or '@' not in email:
            errors['email'] = "请输入有效的邮箱地址"
    
    return errors

# 4. 使用断言进行调试
def divide_numbers(a: float, b: float) -> float:
    """除法运算"""
    assert isinstance(a, (int, float)), f"a 必须是数字，得到 {type(a)}"
    assert isinstance(b, (int, float)), f"b 必须是数字，得到 {type(b)}"
    assert b != 0, "除数不能为零"
    
    return a / b

# 测试函数
items = [
    {"name": "苹果", "price": 5.5},
    {"name": "香蕉", "price": "3.2"},  # 字符串价格
    {"name": "橙子", "price": None},   # 无效价格
]

print(f"总价: {calculate_total(items)}")

# 测试类型转换
test_values = [42, "123.45", "  678  ", "abc", None, [], True]
for value in test_values:
    result = safe_convert_to_number(value)
    print(f"{repr(value):15} -> {result}")

# 测试输入验证
user_data = {
    "name": "张三",
    "email": "zhangsan@example.com",
    "age": "25"
}

validation_errors = validate_user_input(user_data)
if validation_errors:
    print(f"验证错误: {validation_errors}")
else:
    print("输入验证通过")
```

```javascript !! js
// JavaScript 类型系统最佳实践

// 1. 使用 TypeScript 风格的 JSDoc 注解
/**
 * 计算商品总价
 * @param {Array<{name: string, price: string|number}>} items 商品列表
 * @returns {number} 总价
 */
function calculateTotal(items) {
    let total = 0;
    for (const item of items) {
        const price = parseFloat(item.price);
        if (!isNaN(price) && isFinite(price)) {
            total += price;
        }
    }
    return total;
}

// 2. 安全的类型转换
/**
 * 安全地将值转换为数字
 * @param {any} value 要转换的值
 * @returns {number|null} 转换结果或 null
 */
function safeConvertToNumber(value) {
    if (value === null || value === undefined) {
        return null;
    }
    
    if (typeof value === 'number') {
        return isNaN(value) ? null : value;
    }
    
    if (typeof value === 'string') {
        const cleaned = value.trim();
        if (cleaned === '') {
            return null;
        }
        const result = parseFloat(cleaned);
        return isNaN(result) ? null : result;
    }
    
    if (typeof value === 'boolean') {
        return value ? 1 : 0;
    }
    
    return null;
}

// 3. 严格模式下的类型检查
function strictTypeCheck(value, expectedType) {
    const actualType = typeof value;
    if (actualType !== expectedType) {
        throw new TypeError(`Expected ${expectedType}, got ${actualType}`);
    }
    return true;
}

// 4. 输入验证
/**
 * 验证用户输入
 * @param {Object} data 用户数据
 * @returns {Object} 错误信息对象
 */
function validateUserInput(data) {
    const errors = {};
    
    // 检查必需字段
    const requiredFields = ['name', 'email', 'age'];
    for (const field of requiredFields) {
        if (!(field in data) || !data[field]) {
            errors[field] = `${field} 是必需的`;
        }
    }
    
    // 类型验证
    if ('age' in data) {
        const age = safeConvertToNumber(data.age);
        if (age === null || age < 0 || age > 150) {
            errors.age = "年龄必须是 0-150 之间的数字";
        }
    }
    
    if ('email' in data) {
        const email = data.email;
        if (typeof email !== 'string' || !email.includes('@')) {
            errors.email = "请输入有效的邮箱地址";
        }
    }
    
    return errors;
}

// 5. 使用严格相等比较
function strictEquals(a, b) {
    // 使用 === 而不是 ==
    return a === b;
}

// 6. 空值安全访问
function safeGet(obj, key, defaultValue = null) {
    if (obj === null || obj === undefined) {
        return defaultValue;
    }
    
    if (typeof obj !== 'object') {
        return defaultValue;
    }
    
    return obj.hasOwnProperty(key) ? obj[key] : defaultValue;
}

// 7. 类型守卫函数
function isString(value) {
    return typeof value === 'string';
}

function isNumber(value) {
    return typeof value === 'number' && !isNaN(value) && isFinite(value);
}

function isArray(value) {
    return Array.isArray(value);
}

function isObject(value) {
    return value !== null && typeof value === 'object' && !Array.isArray(value);
}

// 测试函数
const items = [
    {name: "苹果", price: 5.5},
    {name: "香蕉", price: "3.2"},  // 字符串价格
    {name: "橙子", price: null},   // 无效价格
    {name: "葡萄", price: "abc"},  // 无效字符串
];

console.log(`总价: ${calculateTotal(items)}`);

// 测试类型转换
const testValues = [42, "123.45", "  678  ", "abc", null, undefined, [], true, false, NaN];
console.log("\n类型转换测试:");
testValues.forEach(value => {
    const result = safeConvertToNumber(value);
    console.log(`${String(value).padEnd(15)} -> ${result}`);
});

// 测试输入验证
const userData = {
    name: "张三",
    email: "zhangsan@example.com",
    age: "25"
};

const validationErrors = validateUserInput(userData);
if (Object.keys(validationErrors).length > 0) {
    console.log(`验证错误:`, validationErrors);
} else {
    console.log("输入验证通过");
}

// 类型守卫测试
console.log("\n类型守卫测试:");
const testData = [42, "hello", [], {}, null, undefined, NaN];
testData.forEach(value => {
    console.log(`值: ${value}`);
    console.log(`  isString: ${isString(value)}`);
    console.log(`  isNumber: ${isNumber(value)}`);
    console.log(`  isArray: ${isArray(value)}`);
    console.log(`  isObject: ${isObject(value)}`);
});
```
</PythonEditor>

## 小结

本模块深入对比了 Python 和 JavaScript 的动态类型系统：

### 关键差异

1. **类型强度**：Python 是强类型，JavaScript 是弱类型
2. **隐式转换**：JavaScript 有更多隐式类型转换规则
3. **真值判断**：JavaScript 中空数组和空对象是真值
4. **相等比较**：JavaScript 有 `==` 和 `===` 两种比较方式
5. **特殊值**：JavaScript 有 `undefined` 和 `NaN` 等特殊值

### 最佳实践

1. **JavaScript 中优先使用 `===` 进行比较**
2. **明确处理 `null` 和 `undefined`**
3. **使用类型守卫函数进行类型检查**
4. **避免依赖隐式类型转换**
5. **使用严格的输入验证**

下一个模块我们将学习 JavaScript 的函数和作用域机制，理解闭包、this 绑定等重要概念。

---

准备好深入了解 JavaScript 的函数特性了吗？让我们继续下一个模块的学习！
